//
//  SqliteDbTool.m
//  CareRingApp
//
//  Created by Linktop on 2024/6/5.
//

#import "SqliteDbTool.h"

@implementation SqliteDbTool
{
    sqlite3_stmt * _statement;
    NSMutableDictionary *_columnNameToIndexMap;
}

- (instancetype)initWithStmt:(sqlite3_stmt *)statement
{
    self = [super init];
    if (self) {
        _statement = statement;
    }
    return self;
}

- (int)intForColumn:(NSString*)columnName {
    return [self intForColumnIndex:[self columnIndexForName:columnName]];
}

- (int)intForColumnIndex:(int)columnIdx {
    return sqlite3_column_int(_statement, columnIdx);
}

- (long)longForColumn:(NSString*)columnName {
    return [self longForColumnIndex:[self columnIndexForName:columnName]];
}

- (long)longForColumnIndex:(int)columnIdx {
    return (long)sqlite3_column_int64(_statement, columnIdx);
}

- (long long int)longLongIntForColumn:(NSString*)columnName {
    return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]];
}

- (long long int)longLongIntForColumnIndex:(int)columnIdx {
    return sqlite3_column_int64(_statement, columnIdx);
}

- (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName {
    return [self unsignedLongLongIntForColumnIndex:[self columnIndexForName:columnName]];
}

- (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx {
    return (unsigned long long int)[self longLongIntForColumnIndex:columnIdx];
}

- (BOOL)boolForColumn:(NSString*)columnName {
    return [self boolForColumnIndex:[self columnIndexForName:columnName]];
}

- (BOOL)boolForColumnIndex:(int)columnIdx {
    return ([self intForColumnIndex:columnIdx] != 0);
}

- (double)doubleForColumn:(NSString*)columnName {
    return [self doubleForColumnIndex:[self columnIndexForName:columnName]];
}

- (double)doubleForColumnIndex:(int)columnIdx {
    return sqlite3_column_double(_statement, columnIdx);
}

- (NSString *)stringForColumnIndex:(int)columnIdx {
    
    if (sqlite3_column_type(_statement, columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count(_statement)) {
        return nil;
    }
    
    const char *c = (const char *)sqlite3_column_text(_statement, columnIdx);
    
    if (!c) {
        // null row.
        return nil;
    }
    
    return [NSString stringWithUTF8String:c];
}

- (NSString*)stringForColumn:(NSString*)columnName 
{
    return [self stringForColumnIndex:[self columnIndexForName:columnName]];
}

- (NSDate*)dateForColumn:(NSString*)columnName 
{
    return [self dateForColumnIndex:[self columnIndexForName:columnName]];
}

- (NSDate*)dateForColumnIndex:(int)columnIdx 
{
    
    if (sqlite3_column_type(_statement, columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count(_statement)) 
    {
        return nil;
    }
    
    return [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]];
}


- (NSData*)dataForColumn:(NSString*)columnName 
{
    return [self dataForColumnIndex:[self columnIndexForName:columnName]];
}

- (NSData*)dataForColumnIndex:(int)columnIdx 
{
    
    if (sqlite3_column_type(_statement, columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count(_statement)) {
        return nil;
    }
    
    const char *dataBuffer = sqlite3_column_blob(_statement, columnIdx);
    int dataSize = sqlite3_column_bytes(_statement, columnIdx);

    if (dataBuffer == NULL) {
        return nil;
    }
    
    return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize];
}


- (NSData*)dataNoCopyForColumn:(NSString*)columnName 
{
    return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]];
}

- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx 
{
    
    if (sqlite3_column_type(_statement, columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count(_statement)) {
        return nil;
    }
  
    const char *dataBuffer = sqlite3_column_blob(_statement, columnIdx);
    int dataSize = sqlite3_column_bytes(_statement, columnIdx);
    
    NSData *data = [NSData dataWithBytesNoCopy:(void *)dataBuffer length:(NSUInteger)dataSize freeWhenDone:NO];
    
    return data;
}


- (BOOL)columnIndexIsNull:(int)columnIdx 
{
    return sqlite3_column_type(_statement, columnIdx) == SQLITE_NULL;
}

- (BOOL)columnIsNull:(NSString*)columnName 
{
    return [self columnIndexIsNull:[self columnIndexForName:columnName]];
}


- (int)columnIndexForName:(NSString*)columnName
{
    columnName = [columnName lowercaseString];
    
    NSNumber *n = [[self columnNameToIndexMap] objectForKey:columnName];
    
    if (n != nil) {
        return [n intValue];
    }
    
    NSLog(@"Warning: I could not find the column named '%@'.", columnName);
    
    return -1;
}

- (NSMutableDictionary *)columnNameToIndexMap 
{
    if (!_columnNameToIndexMap) {
        int columnCount = sqlite3_column_count(_statement);
        _columnNameToIndexMap = [[NSMutableDictionary alloc] initWithCapacity:(NSUInteger)columnCount];
        int columnIdx = 0;
        for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
            [_columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx]
                                      forKey:[[NSString stringWithUTF8String:sqlite3_column_name(_statement, columnIdx)] lowercaseString]];
        }
    }
    return _columnNameToIndexMap;
}
@end
